<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <ul>
        <li>xxx</li>
        <li>yyy</li>
        <li>zzz</li>
    </ul>
    <script>
        // 其实...扩展运算符就是根据iterator迭代器实现的

        // 12-1.html文件中的注释里说到，原生支持for of的数据类型里是不包括object的，我们来试下
        // let obj = {
        //     0:'a',
        //     1:'b',
        //     2:'c',
        // }
        // for(let key of obj){//报错: Uncaught TypeError: obj is not iterable
        //     console.log(key);
        // }

        // 这是因为对象类型是非线性的, 所以想要使用for of遍历一个对象，需要自己埋迭代器，自己写方法

        // 也许你会有疑问，那么for in对于对象不是已经很好用了吗，为啥还要费大劲自己写个支持for of的？从开发的角度来说，你的这个疑问是有道理的，但是我们把目光放得高一点，假设以后我们要封装一个对象，这个对象里的很多属性我们不想让别人能随便遍历到，后续我们也会讲到私有属性这个知识点。那么我们自己写一个支持for of的遍历就尤为重要了，这样别人可以通过for of获取到我们每个属性对应的值，但是永远不会获取到我们这个属性。

        // 先看一个场景, 假设我们现在有个对象，我们希望别人使用for of遍历时，遍历的是list数组，而不是obj2这个对象，这个时候你可能又有疑问了，我直接for of遍历这个list数组不好么，为啥要自己写一个在obj2里，还是那句话，未来list是个私有属性，别人访问不到的。
        let obj2 = {
            code: 200,
            name: 'mikaisa',
            list: ['111', '222', '333'],
            // 12-1.html中已经说过，一个数据结构只要具有Symbol.iterator属性，就可以认为是“可遍历的”(iterable) 。
            [Symbol.iterator]() {//其实这就相当于你自己写了iterator的源码
                let index = 0;
                // 该方法返回一个对象，里面有个next方法，该方法返回一个对象，这个对象的value为遍历到的值，done为是否结束循环的标记。所以这个迭代器就像个指针，你需要让next方法每调用一次，指针就指向下一个值，直到指向末尾
                return {
                    next: () => {//利用箭头函数避免this指向的问题，从而能拿到list
                        return {
                            value: this.list[index++],//利用闭包，让index不会被回收
                            done: index == this.list.length+1  ? true : false//这一步其实有点难懂，举个例子，当index=2的时候，因为value中index++后，index已经变成了3，如果直接判断index==this.list.length，那done就直接为true了，而当done为true时，会被判定为循环已结束，那么value也就不会被循环遍历出来了。所以我们要把this.list.length去+1，从而让index为4时，done才会被赋值为true, 避免了这个问题
                        }
                    }
                }
            }
        }

        let ite = obj2[Symbol.iterator]();

        for(let key of obj2){
            console.log(key);
        }

        // 接下来我们证明一下字符串和arguments、nodelist也可以for of
        for(let char of 'mikaisa'){
            console.log(char);
        }

        (function (){
            for(let arg of arguments){
                console.log(arg);
            }
        })(1,2,3,4,5)

        for(let node of document.querySelectorAll('li')){
            console.log(node);
        }
        // 另外，我们可以根据扩展运算符搞出一个快速将nodelist转换为数组的方法
        let arr = [...document.querySelectorAll('li')];
        console.log(arr,arr instanceof Array,Array.isArray(arr));
    </script>
</body>

</html>